module CPF
  def is_cpf?
    cpf = self.normalize_cpf
    return false unless cpf.length == 11
    return false if cpf.match(/^[0]{11}|[1]{11}|[2]{11}|[3]{11}|[4]{11}|[5]{11}|[6]{11}|[7]{11}|[8]{11}|[9]{11}$/)
    
    mod11 = lambda do |n|
      fatores = Array.new
      n.downto(2) { |d| fatores << d }
      digitos_multiplicados = Array.new
      0.upto(n - 2) { |n| digitos_multiplicados << cpf[n,1].to_i * fatores[n].to_i }
      total = digitos_multiplicados.inject(0) { |total, d| total + d }
      resto = total % 11
      digito_verificador = (resto < 2) ? 0 : 11 - resto
    end

    dv1 = mod11.call(10)
    dv2 = mod11.call(11)
    
    (cpf[-2,2] == "#{dv1}#{dv2}") ? true : false
  end
  
  def normalize_cpf
    self.gsub(/\D*/, "")
  end  

  def normalize_cpf!
    self.gsub!(/\D*/, "")
  end
  
  def to_cpf
    rgx = self.match(/^(\d{3})(\d{3})(\d{3})(\d{2})$/)    
    (self.is_cpf?) ? "#{rgx[1]}.#{rgx[2]}.#{rgx[3]}-#{rgx[4]}" : self
  end
  
  def to_cpf!
    rgx = self.match(/^(\d{3})(\d{3})(\d{3})(\d{2})$/)    
    (self.is_cpf?) ? self.replace("#{rgx[1]}.#{rgx[2]}.#{rgx[3]}-#{rgx[4]}") : self
  end
end

class String
  include CPF
end